package checkers3d.logic;

import checkers3d.presentation.*;

/**
 * An interface for board objects that exist on the game board(s) can have their
 * own state changed by 'touching' another object, change the state of another
 * by 'touching' it.
 *
 * A touch event is detected by the Game object when two IBoardObjects temporary
 * exist in the same position (as in the case where a piece is moving along a
 * path to a new location on the board). Game then calls the appropriate
 * functions in each object and resolves any BoardObjectTouchEffects that either
 * of the two objects requested.
 *
 * @author      Ruben Acuna
 */
public interface IBoardObject extends IDrawable, IDrawableSelectiveVisibility
{
    //FIXME: setupCount and isValidSetupPosition were static! I was hoping that
    //we could define a static variable within an interface but it looks like we
    //can't. Hack round this by making setupCount and isValidSetupPosition not
    //static and instancing a generic copy during game setup to get access to
    //them. getSetupCount() is currently replacing setupCount.

    /**
     * Returns the total number of pieces of this type which a given player
     * may setup, and later control, each game.
     *
     * @param boardSizeX The width of the board.
     * @param boardSizeY The height of the board.
     * @param boardSizeZ The number of boards.
     * @return The number of pieces.
     */
    int getSetupCount(int boardSizeX, int boardSizeY, int boardSizeZ);

    /**
     * Returns the Player object that currently controls the IBoardObject.
     *
     * @return Returns Player object that controls this object.
     */
    Player getOwner();

    /**
     * Sets the Player object that controls the IBoardObject.
     *
     * @param player The player object which owns this object.
     */
    void setOwner(Player player);

    /**
     * Returns true if IBoardObject prevents other objects from existing in the
     * same location.
     *
     * @return Returns true if object blocks its current location.
     */
    boolean isBlocking();

    /**
     * Returns true if the IBoardObject may be placed on a certain location
     * during the game setup. A reference to the playing surface is passed as
     * well as the position this piece could be placed.
     *
     * @param playingSurface3D Reference the playing surface.
     * @param location Location this piece could be placed.
     * @return True if object can be placed on location before game.
     */
    boolean isValidSetupPosition(PlayingSurface3D playingSurface3D, Point3D location);


    /**
     * Event to let the IBoardObject know that it was touched by another object
     * entering this object's location. Returns an effect that the Game will
     * apply to the other object.
     *
     * @param other The object that touched this object.
     * @return      An effect that should be applied to the other object.
     */
    BoardObjectTouchEffect onTouch(IBoardObject other);

    /**
     * Returns a new instance of this object type with all local variables the
     * same.
     *
     * @return A new instance of this object.
     */
    IBoardObject clone();

    /**
     * Returns a string containing data about this object needed to save it's
     * state.
     *
     * @return String with object name and it's owner.
     * @see IBoardObject
     */
    String getDataAsString();
}